package com.ccrfid.rmc6.resource.alarm;

import com.ccrfid.rmc6.appconfig.auth.Secured;
import com.ccrfid.rmc6.appconfig.exception.pojo.AppException;
import com.ccrfid.rmc6.entity.alarm.AlarmNotifyRecordView;
import com.ccrfid.rmc6.entity.alarm.AlarmRecordEntity;
import com.ccrfid.rmc6.pojo.dto.alarm.AlarmNotifyRecordCountDto;
import com.ccrfid.rmc6.pojo.param.PageParam;
import com.ccrfid.rmc6.repository.search.Criterion;
import com.ccrfid.rmc6.repository.search.SearchCriteria;
import com.ccrfid.rmc6.resource.auth.pojo.UserPrincipal;
import com.ccrfid.rmc6.service.alarm.AlarmRecordService;
import com.ccrfid.rmc6.util.RegexUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.SecurityContext;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.sql.Timestamp;
import java.util.List;

@Secured
@Path("")
@Produces(MediaType.APPLICATION_JSON)
public class AlarmRecordResource {
    @Context
    private SecurityContext securityContext;
    @Autowired
    private AlarmRecordService alarmRecordService;

    @GET
    @Path("alarm-records")
    public Page<AlarmRecordEntity> getAlarmRecords(@QueryParam("personnelQuery") String personnelQuery,
                                                   @QueryParam("personnelId") String personnelId,
                                                   @QueryParam("locationName") String locationName,
                                                   @QueryParam("alarmType") List<Integer> alarmTypeList,
                                                   @QueryParam("alarmLevel") Integer alarmLevel,
                                                   @QueryParam("closed") Integer closed,
                                                   @QueryParam("startTime") Timestamp startTime,
                                                   @QueryParam("endTime") Timestamp endTime,
                                                   @BeanParam PageParam pageParam) {
        SearchCriteria criteria = SearchCriteria.Builder.create();
        if (!StringUtils.isEmpty(personnelQuery)) {
            if (RegexUtil.maybeCardNumber(personnelQuery)) {
                criteria.add(new Criterion("cardNumber", Criterion.Operator.EQ, Integer.parseInt(personnelQuery)));
            }
            if (RegexUtil.maybeNameAcronym(personnelQuery)) {
                criteria.add(new Criterion("nameAcronym", Criterion.Operator.LIKE, personnelQuery + '%'));
            }
            if (RegexUtil.containChinese(personnelQuery)) {
                criteria.add(new Criterion("personnelName", Criterion.Operator.LIKE, '%' + personnelQuery + '%'));
            }
        }
        if (personnelId != null) {
            criteria.add(new Criterion("personnelId", Criterion.Operator.EQ, personnelId));
        }
        if (locationName != null) {
            criteria.add(new Criterion("locationName", Criterion.Operator.EQ, locationName));
        }
        if (alarmTypeList != null && alarmTypeList.size() > 0) {
            criteria.add(new Criterion("alarmType", Criterion.Operator.IN, alarmTypeList));
        }
        if (alarmLevel != null) {
            criteria.add(new Criterion("alarmLevel", Criterion.Operator.EQ, alarmLevel));
        }
        if (closed != null) {
            criteria.add(new Criterion("closed", Criterion.Operator.EQ, closed));
        }
        if (startTime != null) {
            criteria.add(new Criterion("alarmTime", Criterion.Operator.GTE, startTime));
        }
        if (endTime != null) {
            criteria.add(new Criterion("alarmTime", Criterion.Operator.LTE, endTime));
        }
        PageRequest pageRequest;
        if (pageParam.getOrders() != null && pageParam.getOrders().size() > 0) {
            pageRequest = PageRequest.of(pageParam.getPageNumber(), pageParam.getPageSize(), Sort.by(pageParam.getOrders()));
        } else {
            pageRequest = PageRequest.of(pageParam.getPageNumber(), pageParam.getPageSize());
        }
        return alarmRecordService.getAlarmRecords(criteria, pageRequest);
    }

    @GET
    @Path("personal-alarm-records")
    public Page<AlarmNotifyRecordView> getPersonalAlarmNotifyRecords(@QueryParam("read") Integer read,
                                                                     @QueryParam("personnelQuery") String personnelQuery,
                                                                     @QueryParam("personnelId") String personnelId,
                                                                     @QueryParam("locationName") String locationName,
                                                                     @QueryParam("alarmType") List<Integer> alarmTypeList,
                                                                     @QueryParam("alarmLevel") Integer alarmLevel,
                                                                     @QueryParam("closed") Integer closed,
                                                                     @QueryParam("startTime") Timestamp startTime,
                                                                     @QueryParam("endTime") Timestamp endTime,
                                                                     @QueryParam("alarmRuleName") String alarmRuleName,
                                                                     @BeanParam PageParam pageParam) {
        SearchCriteria criteria = SearchCriteria.Builder.create();
        if (read != null) {
            criteria.add(new Criterion("read", Criterion.Operator.EQ, read));
        }
        if (!StringUtils.isEmpty(personnelQuery)) {
            if (RegexUtil.maybeCardNumber(personnelQuery)) {
                criteria.add(new Criterion("cardNumber", Criterion.Operator.EQ, Integer.parseInt(personnelQuery)));
            }
            if (RegexUtil.maybeNameAcronym(personnelQuery)) {
                criteria.add(new Criterion("nameAcronym", Criterion.Operator.LIKE, personnelQuery + '%'));
            }
            if (RegexUtil.containChinese(personnelQuery)) {
                criteria.add(new Criterion("personnelName", Criterion.Operator.LIKE, '%' + personnelQuery + '%'));
            }
        }
        if (personnelId != null) {
            criteria.add(new Criterion("personnelId", Criterion.Operator.EQ, personnelId));
        }
        if (locationName != null) {
            criteria.add(new Criterion("locationName", Criterion.Operator.EQ, locationName));
        }
        if (alarmTypeList != null && alarmTypeList.size() > 0) {
            criteria.add(new Criterion("alarmType", Criterion.Operator.IN, alarmTypeList));
        }
        if (alarmLevel != null) {
            criteria.add(new Criterion("alarmLevel", Criterion.Operator.EQ, alarmLevel));
        }
        if (closed != null) {
            criteria.add(new Criterion("closed", Criterion.Operator.EQ, closed));
        }
        if (startTime != null) {
            criteria.add(new Criterion("alarmTime", Criterion.Operator.GTE, startTime));
        }
        if (endTime != null) {
            criteria.add(new Criterion("alarmTime", Criterion.Operator.LTE, endTime));
        }
        if(alarmRuleName != null){
            criteria.add(new Criterion("alarmRuleName", Criterion.Operator.EQ, alarmRuleName));
        }
        UserPrincipal userPrincipal = (UserPrincipal) securityContext.getUserPrincipal();
        Long notifyPersonnelId = userPrincipal.getPersonnelId();
        if (notifyPersonnelId != null) {
            criteria.add(new Criterion("notifyPersonnelId", Criterion.Operator.EQ, notifyPersonnelId));
        } else {
            criteria.add(new Criterion("notifyPersonnelId", Criterion.Operator.EQ, 0));
        }
        PageRequest pageRequest;
        if (pageParam.getOrders() != null && pageParam.getOrders().size() > 0) {
            pageRequest = PageRequest.of(pageParam.getPageNumber(), pageParam.getPageSize(), Sort.by(pageParam.getOrders()));
        } else {
            pageRequest = PageRequest.of(pageParam.getPageNumber(), pageParam.getPageSize());
        }
        return alarmRecordService.getPersonalAlarmNotifyRecords(criteria, pageRequest);
    }

    //标记某条告警已读
    @PUT
    @Path("personal-alarm-records/{alarmNotifyRecordId}/mark-read")
    public Boolean markReadPersonalAlarmRecord(@PathParam("alarmNotifyRecordId") Long alarmNotifyRecordId)
            throws AppException {
        UserPrincipal userPrincipal = (UserPrincipal) securityContext.getUserPrincipal();
        Long notifyPersonnelId = userPrincipal.getPersonnelId();
        return alarmRecordService.markReadPersonalAlarmRecord(alarmNotifyRecordId);
    }

    //批量标记已读
    @PUT
    @Path("personal-alarm-records/batch-mark-read")
    @Consumes(MediaType.APPLICATION_JSON)
    public Boolean markReadPersonalAlarmRecords(List<Long> idList) throws AppException {
        return alarmRecordService.markReadPersonalAlarmRecords(idList);
    }

    //全部标记已读
    @PUT
    @Path("personal-alarm-records/all-mark-read")
    public Boolean markReadAllPersonalAlarmRecords(@Context SecurityContext securityContext) {
        UserPrincipal userPrincipal = (UserPrincipal) securityContext.getUserPrincipal();
        return alarmRecordService.markReadAllPersonalAlarmRecords(userPrincipal.getUserAccount());
    }
    //获取告警记录数量接口（已读，未读，全部）
    @GET
    @Path("personal-alarm-records/counts")
    public AlarmNotifyRecordCountDto getPersonalAlarmNotifyRecordsCount(){
        UserPrincipal userPrincipal = (UserPrincipal) securityContext.getUserPrincipal();
        Long notifyPersonnelId = userPrincipal.getPersonnelId();
        if (notifyPersonnelId != null) {
            return alarmRecordService.getAlarmNotifyRecordCount(notifyPersonnelId);
        } else {
            return new AlarmNotifyRecordCountDto(0,0,0);
        }
    }

}
